#include <fstream>
#include <ios>
#include "XMLParser.h"


XMLParser::XMLParser()
{
    this->size = 0;
    this->currentNode = NULL;
    this->currPos = 0;
}

XMLParser::~XMLParser()
{
}


void	XMLParser::startParsing()
{
    if (this->buffer.empty())
        return;
    this->currPos = 0;
    this->inNode = false;
    while (this->currPos < this->size)
    {
        this->getNextNode();
    }
}

void	XMLParser::getNextNode()
{
    size_t	min = this->size;
    void	(XMLParser::*extractFunc)(void) = NULL;
    if (min > this->buffer.find("<!--", this->currPos))
    {
        min = this->buffer.find("<!--", this->currPos);
        extractFunc = &XMLParser::getComment;
    }
    if (min > this->buffer.find("<?", this->currPos))
    {
        min = this->buffer.find("<?", this->currPos);
        extractFunc = &XMLParser::getXmlDeclaration;
    }
    if (min > this->buffer.find("</", this->currPos))
    {
        min = this->buffer.find("</", this->currPos);
        extractFunc = &XMLParser::getClosedNode;
    }
    if (min > this->buffer.find("<", this->currPos))
    {
        min = this->buffer.find("<", this->currPos);
        extractFunc = &XMLParser::getNode;
    }
    if (this->inNode)
        this->getData(min - this->currPos);
    this->currPos = min;
    if (extractFunc)
        (this->*extractFunc)();
}

void    XMLParser::getData(int size)
{
    this->dataElement(this->buffer.substr(this->currPos, size));
}

void	XMLParser::getComment(void)
{
    this->inNode = false;
    this->currPos += 4;
    this->currPos = this->buffer.find("-->", this->currPos) + 3;
}

void	XMLParser::getXmlDeclaration(void)
{
    this->inNode = false;
    this->currPos += 2;
    this->currPos = this->buffer.find("?>", this->currPos) + 2;
}

void	XMLParser::getNode(void)
{
    this->inNode = false;
    this->currPos += 1;
    int decal = 2;
    size_t	min = this->buffer.find("/>", this->currPos);
    if (min > this->buffer.find(">", this->currPos))
    {
        min = this->buffer.find(">", this->currPos);
        this->inNode = true;
        decal = 1;
    }
    XMLNode *newNode = new XMLNode(this->buffer.substr(this->currPos, min - this->currPos));
    this->startElement(newNode);
    this->currPos = min + decal;;
}

void	XMLParser::getClosedNode(void)
{
    this->inNode = false;
    this->currPos += 2;
    XMLNode *newNode = new XMLNode(this->buffer.substr(this->currPos, this->buffer.find(">", this->currPos) - this->currPos));
    this->endElement(newNode);
    this->currPos = this->buffer.find(">", this->currPos) + 1;
}


void	XMLParser::setContent(const char* path)
{
    std::ifstream		file;

    file.open(path, std::ios::in);
    if (!file.is_open())
        throw (XMLException("Error form XMLParser : can't open xml file"));
    std::string line;
    while (std::getline(file, line))
        this->buffer += line;
    this->size = this->buffer.size();
}

void	XMLParser::setContent(const std::string& ptr)
{
    if (ptr.empty())
        throw (XMLException("Error form XMLParser : xml flux is empty"));
    this->buffer = ptr;
    this->size = this->buffer.size();
}
